<?php
/**
 * DMFramework
 * 
 * @license Copyright 2012 Dillen Meijboom under the Apache license version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 * @author Dillen Meijboom <info@dillenm.nl>
 * @url http://dmframework.nl
 */

/**
 * The is the "main" class of this Framework withouth this class nothing will work
 * (except the library files of course). You can use the buffer and config class staticly.
 * 
 * @license Copyright 2012 Dillen Meijboom under the Apache license version 2.0 (http://apache.org/licenses/LICENSE-2.0)
 * @author Dillen Meijboom <info@dillenm.nl>
 * @package System.Core
 */
class Dmf_Application
{
    /**
     * All configuration settings
     * 
     * @var array
     */
    private $_config;
    
    /**
     * The autoloader
     * 
     * @var Dmf_Autoloader 
     */
    private $_autoloader;
    
    /**
     * Application instance
     * 
     * @var Dmf_Application
     */
    private static $_instance;
    
    /**
     * Get application instance
     * 
     * @return Dmf_Application 
     */
    public static function getInstance()
    {
        return self::$_instance;
    }
    
    /**
     * Get the autoloader instance
     * 
     * @return Dmf_Autoloader 
     */
    public function getAutoloader()
    {
        return $this->_autoloader;
    }
    
    /**
     * Get the configuration class
     * 
     * @return Dmf_Config_Ini|Dmf_Config_Php 
     */
    public function getConfig()
    {
        return $this->_config;
    }
    
    /**
     * Create the application 
     * 
     * @param Dmf_Config_Ini|Dmf_Config_Php|null
     */
    public function create( $config = null )
    {
        //Include dependencies since there is no autoloader yet
        include( 'system/core/Stdclass.php' );
        include( 'system/core/config/Ini.php' );
        include( 'system/core/error/Handler.php' );
        include( 'system/core/Autoloader.php' );
        
        //Getting and setting dependencies
        $this->_config = $config === null ? new Dmf_Config_Ini( 'application/configs/default.ini' ) : $config;
        $this->_autoloader = Dmf_Autoloader::getInstance();
        
        self::$_instance = $this;
        
        //Load main configuration
        $this->_setConfiguration();
        $this->_setHelpers();
        
        //Set autoloader and exception handler
        spl_autoload_register( array( $this->_autoloader, 'loadClass' ) );
        set_exception_handler( array( 'Dmf_Error_Handler', 'handle' ) );
        set_error_handler( array( 'Dmf_Error_Handler', 'handlePhp' ), E_ALL );
        
        //Also catch fatal errors (PHP 5.3 >)
        if ( function_exists( 'register_shutdown_function' ) ) 
        {
            register_shutdown_function( array( 'Dmf_Error_Handler', 'shutdown' ) ); 
        }
        
        if ( $this->_config->asObject()->bootstrap->enabled )
        {
            //Initialize application
            $this->_loadBootstrap();
        }
    }
    
    /**
     * Set main configuration 
     */
    private function _setConfiguration()
    {
        //Set error reporting
        if ( $this->_config->asObject()->application->debug )
        {
            @error_reporting( E_ALL );
            @ini_set( 'display_errors', 1 );
        }
        else
        {
            @error_reporting( 0 );
            @ini_set( 'display_errors', 0 );
        }
        
        if ( isset( $this->_config->asObject()->phpsettings ) )
        {
            $this->_setPhpSettings( $this->_config->asObject()->phpsettings->asArray() );
        }
        else
        {
            $this->_setPhpSettings();
        }
    }
    
    private function _loadBootstrap()
    {
        if ( ! file_exists( 'application/Bootstrap.php' ) )
        {
            throw new Exception( '<b>Core-fatal error:</b> The bootstrap file: "application/Bootstrap.php" does not exists, withouth it DMFramework can\'t startup.' );
        }
        
        include( 'application/Bootstrap.php' );
        
        //Load the bootstrapper
        $bootstrap = new Dmf_Bootstrap( $this );
        
        $bootstrap->__runApplication();
    }
    
    /**
     * Set all CORE-helpers
     */
    private function _setHelpers()
    {
        /**
         * Printf but then without predefined types.
         * 
         * @param string $string
         * @param array $args
         * @return type 
         */
        function sgetf( $string, $args )
        {
            for ( $i = 0; $i < count( $args ); ++$i )
            {
                if ( $args[ $i ] === false ) continue;
                
                $string = str_replace( '%' . ( $i + 1 ), $args[ $i ], $string );
            }
            
            return $string;
        }
    }
    
    /**
     * Set all giving PHP settings
     * 
     * @param type $settings 
     */
    private function _setPhpSettings( $settings = array() )
    {
        @ini_set( 'magic_quotes', 'Off' );
        @ini_set( 'session.use_cookies', 0 );
        
        //Disable magic quotes
        if ( phpversion() < 5.3 && function_exists( 'get_magic_quotes_gpc' ) && @get_magic_quotes_gpc() )
        {
            @set_magic_quotes_runtime( 0 );
        }
        
        foreach( $settings as $key => $value )
        {
            @ini_set( $key, $value );
        }
    }
    
    /**
     * Called on Application end 
     */
    public function __destruct()
    {
        if ( function_exists( 'gc_collect_cycles' ) ) gc_collect_cycles();
        
        $vars = get_defined_vars();
        
        foreach( $vars as &$var )
        {
            unset( $var );
        }
    }
}